﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Media3D;
using System.Windows.Controls;
using System.Windows.Media.Animation;

namespace MagicCube
{
    public class MagicCubeModel
    {
        #region 魔方属性

        //阶数
        private const int Stairs = 3;
        //3D环境
        private Viewport3D viewPort = new Viewport3D();
        //魔方组
        private Model3DGroup magicCubeGroup = new Model3DGroup();
        //正方体列表
        private List<CubeModel> cubes = new List<CubeModel>();
        //临时旋转列表
        private List<CubeModel> rotateCubes = new List<CubeModel>();
        //方块间的偏移值
        private double[] deviant = new double[] { 1.01, 0, -1.01, };

        #endregion

        #region 动画属性

        //面板，用于绑定属性
        private FrameworkElement element = new FrameworkElement();
        //旋转动画
        private Storyboard story = new Storyboard();
        //旋转轴
        private Spindle spindle;
        //旋转方向
        private bool isClockwise = true;
        //动画是否执行中
        private bool isBegining = false;

        #endregion

        #region 外部接口

        /// <summary>
        /// 魔方模型
        /// </summary>
        private ModelVisual3D cubeModel3D = new ModelVisual3D();
        /// <summary>
        /// 获取魔方模型
        /// </summary>
        public ModelVisual3D CubeModel3D 
        { 
            get { return cubeModel3D; } 
        } 

        /// <summary>
        /// 构造器
        /// </summary>
        public MagicCubeModel()
        {
            Create_CubeModel();
        }

        /// <summary>
        /// 生成魔方
        /// </summary>
        public void Create_CubeModel()
        {
            magicCubeGroup.Children.Clear();
            for (int i = 0; i < Stairs; i++)
            {
                for (int j = 0; j < Stairs; j++)
                {
                    for (int k = 0; k < Stairs; k++)
                    {
                        CubeModel cube = new CubeModel(deviant[i], deviant[j], deviant[k]);
                        cubes.Add(cube);
                        magicCubeGroup.Children.Add(cube.CubeGroup);
                    }
                }
            }
            //加入模型
            cubeModel3D.Content = magicCubeGroup;
        }

        /// <summary>
        /// 指定旋转
        /// </summary>
        /// <param name="spindle">旋转轴</param>
        /// <param name="isClockwise">是否顺时针</param>
        /// <param name="groupNumber">旋转组号</param>
        /// <returns>成功或者失败</returns>
        public bool RotateCubeGroup(Spindle spindle, bool isClockwise, int groupNumber)
        {
            if (spindle == Spindle.X && groupNumber >= 1 && groupNumber <= 6) return false;
            if (spindle == Spindle.Y && groupNumber >= 1 && groupNumber <= 3) return false;
            if (spindle == Spindle.Y && groupNumber >= 7 && groupNumber <= 9) return false;
            if (spindle == Spindle.Z && groupNumber >= 4 && groupNumber <= 9) return false;
            if (isBegining) return false;
            isBegining = true;
            SetRotateNature(spindle, isClockwise);
            Find_RotateCube(groupNumber);
            StoryBegin();
            return true;
        }

        /// <summary>
        /// 定位旋转
        /// </summary>
        /// <param name="spindle">旋转轴</param>
        /// <param name="isClockwise">是否顺时针</param>
        /// <param name="groupNumber">旋转组号</param>
        /// <returns>成功或者失败</returns>
        public bool ChangeCubeGroup(Spindle spindle, bool isClockwise, int groupNumber)
        {
            if (spindle == Spindle.X && groupNumber >= 1 && groupNumber <= 6) return false;
            if (spindle == Spindle.Y && groupNumber >= 1 && groupNumber <= 3) return false;
            if (spindle == Spindle.Y && groupNumber >= 7 && groupNumber <= 9) return false;
            if (spindle == Spindle.Z && groupNumber >= 4 && groupNumber <= 9) return false;
            Find_RotateCube(groupNumber);
            foreach (CubeModel cube in rotateCubes)
            {
                cube.UpdateLocation(cube, spindle, isClockwise);
            }
            rotateCubes = null;
            rotateCubes = new List<CubeModel>();
            return true;
        }

        #endregion
   
        #region 旋转处理函数

        //设置旋转属性
        private void SetRotateNature(Spindle spindle, bool isClockwise)
        {
            this.spindle = spindle;
            this.isClockwise = isClockwise; 
        }
        //找出需要旋转的方块组并存入临时旋转组
        private void Find_RotateCube(int groupNumber)
        {
            foreach (CubeModel cube in cubes)
            {
                if (isRotate(cube, groupNumber)) rotateCubes.Add(cube);
            }
        }
        //断是否是需要旋转的方块
        private bool isRotate(CubeModel cube, int groupNumber)
        {
            switch(groupNumber)
            {
                case 0: return true;
                case 1: if (cube.PointC.Z == cube.Length * deviant[0]) return true; break;
                case 2: if (cube.PointC.Z == cube.Length * deviant[1]) return true; break;
                case 3: if (cube.PointC.Z == cube.Length * deviant[2]) return true; break;
                case 4: if (cube.PointC.Y == cube.Length * deviant[0]) return true; break;
                case 5: if (cube.PointC.Y == cube.Length * deviant[1]) return true; break;
                case 6: if (cube.PointC.Y == cube.Length * deviant[2]) return true; break;
                case 7: if (cube.PointC.X == cube.Length * deviant[0]) return true; break;
                case 8: if (cube.PointC.X == cube.Length * deviant[1]) return true; break;
                case 9: if (cube.PointC.X == cube.Length * deviant[2]) return true; break;
            }
            return false;
        }
        //生成并启动动画
        private void StoryBegin()
        {
            element = new FrameworkElement();
            NameScope.SetNameScope(element, new NameScope());
            story = new Storyboard();
            int i = 0;
            foreach (CubeModel cube in rotateCubes)
            {
                story.Children.Add(cube.Rotate_CubeModel(spindle, isClockwise, element, "axis" + i++));
            }
            story.Completed += StoryCompleted;
            story.Begin(element);
        }
        //动画完成后创建帧
        private void StoryCompleted(object sender, EventArgs e)
        {
            foreach (CubeModel cube in rotateCubes) 
            {
                cube.UpdateLocation(cube, spindle, isClockwise);
            }
            rotateCubes.Clear();
            isBegining = false;
        }

        #endregion
    }
}